#define _CRT_SECURE_NO_WARNINGS 1

class MyCircularQueue {
    class ListNode {
    public:
        ListNode(int val = 0, ListNode* next = nullptr, ListNode* prev = nullptr)
        {
            _val = val;
            _next = next;
            _prev = prev;
        }
        int _val;
        ListNode* _next;
        ListNode* _prev;
    };
public:
    MyCircularQueue(int k) {
        _end = _start = new ListNode();
        ListNode* cur = _start;
        while (k--)
        {
            ListNode* node = new ListNode(0, nullptr, cur);
            cur->_next = node;
            cur = cur->_next;
        }
        cur->_next = _start;
        _start->_prev = cur;
    }

    bool enQueue(int value) {
        if (isFull())
            return false;
        _end->_val = value;
        _end = _end->_next;
        return true;
    }

    bool deQueue() {
        if (isEmpty())
            return false;
        _start = _start->_next;
        return true;
    }

    int Front() {
        if (isEmpty())
            return -1;
        return _start->_val;
    }

    int Rear() {
        if (isEmpty())
            return -1;
        return _end->_prev->_val;
    }

    bool isEmpty() {
        if (_start == _end)
            return true;
        return false;
    }

    bool isFull() {
        if (_end->_next == _start)
            return true;
        return false;
    }
private:
    ListNode* _start;
    ListNode* _end;
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue* obj = new MyCircularQueue(k);
 * bool param_1 = obj->enQueue(value);
 * bool param_2 = obj->deQueue();
 * int param_3 = obj->Front();
 * int param_4 = obj->Rear();
 * bool param_5 = obj->isEmpty();
 * bool param_6 = obj->isFull();
 */